/**
Nectarine Utility Project is a software interface for the web system 'demovibes'
Copyright (C) 2010  Alexandre LAURENT

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

website: http://code.google.com/p/nectarine-utility-project/
e-mail: lw.demoscene@gmail.com
**/

#include "mainwindow.h"

#include <QApplication>
#include <QMessageBox>
#include <QInputDialog>

#include <QTabWidget>

#include <QMenuBar>
#include <QMenu>

#include <QFile>
#include <QFileDialog>

#include <QTimer>

#include <QCloseEvent>
#include <QDesktopServices>

#include <QSettings>

#include <QDebug>

#include "Interface/onelinerwidget.h"
#include "Interface/onelinerviewer.h"
#include "Interface/queuewidget.h"
#include "Interface/playerwidget.h"
#include "Interface/loginpromptdialog.h"
#include "Interface/streamspromptdialog.h"
#include "Interface/newspromptdialog.h"
#include "Interface/songinfodialog.h"
#include "Interface/artistinfodialog.h"
#include "Interface/groupinfodialog.h"
#include "Interface/compilationinfodialog.h"
#include "Interface/userinfodialog.h"
#include "Interface/favsdialog.h"
#include "Interface/votewidget.h"
#include "Interface/proxypromptdialog.h"

#include "Web/WebClient.h"

#include "Parser/queuexmlparser.h"
#include "Parser/onelinerxmlparser.h"
#include "Parser/streamparser.h"
#include "Parser/newsparser.h"
#include "Parser/favsparser.h"
#include "Parser/usersparser.h"

#include "Player/player.h"

#include "./Types/song.h"
#include "../Types/artist.h"
#include "../Types/compilation.h"

#include "../utils.h"
#include "../globals.h"


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent),isConnected(false),username(""),userFavorites(),pmRequestedByUser(false)
{
    this->setWindowIcon(QIcon(ICONSDIR + QString("favicon.png")));
    this->resize(500, 500);

    // Construction of the interface
    pTabWidget = new QTabWidget(this);

    pOnelinerWidget = new OnelinerWidget(this);
    pOnelinerWidget->setConnection(false);
    pQueueWidget = new QueueWidget(this);

    pPlayer = new StreamPlayer(/*QUrl("http://demovibes.de:8000/necta128.ogg"),*/this);
    pPlayerWidget = new PlayerWidget(pPlayer->getMediaObject(),pPlayer->getAudioOutput(), pPlayer->getAudioPath(),this);

    this->setCentralWidget(pTabWidget);

    pTabWidget->addTab(pOnelinerWidget, "Oneliner");
    pTabWidget->addTab(pQueueWidget, tr("Queue"));
    pTabWidget->addTab(pPlayerWidget, tr("Player"));

    // Gives some freedom to the user
    pTabWidget->setMovable(true);
    pTabWidget->setTabsClosable(true);

    // Connection
    connect(pTabWidget, SIGNAL(tabCloseRequested(int)), this, SLOT(needTabToClose(int)));

    // Let's start the web client here
    pWebClient = new WebClient(QUrl(DEFAULT_SERVER),this);

    pNPD = NULL;

    // Creation of the menus
    createMenus();

    // Creation of the Timer
    pOnelinerTimer = new QTimer(this);
    pQueueTimer = new QTimer(this);
    pUsersTimer = new QTimer(this);
    pPMTimer = new QTimer(this);

    // Connect the client to the app
    connect(pWebClient, SIGNAL(onelinerReady(void)), this, SLOT(needRefreshOneliner()));
    connect(pWebClient, SIGNAL(queueReady(void)), this, SLOT(needRefreshQueue()));
    connect(pWebClient, SIGNAL(streamReady(void)), this, SLOT(needDisplayStream()));
    connect(pWebClient, SIGNAL(newsReady(void)), this, SLOT(needDisplayNews()));
    connect(pWebClient, SIGNAL(usersOnelineReady()), this, SLOT(needDisplayUsers()));
    connect(pWebClient, SIGNAL(inboxReady()), this, SLOT(needDisplayInbox()));
    connect(pWebClient, SIGNAL(favoritesReady()), this, SLOT(needDisplayFavList()));
    connect(pWebClient, SIGNAL(paginatedFavoritesReady()), this, SLOT(needDisplayFavListPage()));
    connect(pWebClient, SIGNAL(userFavoritesReady()), this, SLOT(needUpdateUserFavorite()));
    connect(pWebClient, SIGNAL(userPaginatedFavoritesReady()), this, SLOT(needUpdateUserPaginatedFavorite()));
    connect(pWebClient, SIGNAL(songReady()), this, SLOT(needDisplaySong()));
    connect(pWebClient, SIGNAL(artistReady()), this, SLOT(needDisplayArtist()));
    connect(pWebClient, SIGNAL(groupReady()), this, SLOT(needDisplayGroup()));
    connect(pWebClient, SIGNAL(compilationReady()), this, SLOT(needDisplayCompilation()));
    connect(pWebClient, SIGNAL(userReady(QString)), this, SLOT(needDisplayUser(QString)));

    connect(pWebClient, SIGNAL(connectionSucceed()), this, SLOT(connectionSucceed()));
    connect(pWebClient, SIGNAL(errorOccured(QString)), this, SLOT(needDisplayWebError(QString)));
    connect(pWebClient, SIGNAL(connectionFailed()), this, SLOT(needDisplayConnectionFailure()));

    connect(pPlayer, SIGNAL(errorOccured(QString)), this, SLOT(needDisplayPlayerError(QString)));
    connect(pPlayer, SIGNAL(playingStateSignal()), this, SLOT(needUpdatePlayerInfo()));

    connect(pOnelinerWidget->getOnelinerViewer(), SIGNAL(needReloadOneliner(void)), this, SLOT(needLoadOneliner()));
    connect(pOnelinerWidget, SIGNAL(needSendMessage(QString)), pWebClient, SLOT(sendOnelinerMessage(QString)));
    connect(pOnelinerWidget, SIGNAL(needRequestUserPage(QString)), pWebClient, SLOT(requestUserPage(const QString)));

    connect(pQueueWidget->getRequestListWidget(), SIGNAL(requestSongPage(int)), pWebClient, SLOT(requestSongPage(int)));
    connect(pQueueWidget->getRequestListWidget(), SIGNAL(requestArtistPage(int)), pWebClient, SLOT(requestArtistPage(int)));
    connect(pQueueWidget->getRequestListWidget(), SIGNAL(requestUserPage(QString)), pWebClient, SLOT(requestUserPage(QString)));
    connect(pQueueWidget->getHistoryListWidget(), SIGNAL(requestSongPage(int)), pWebClient, SLOT(requestSongPage(int)));
    connect(pQueueWidget->getHistoryListWidget(), SIGNAL(requestArtistPage(int)), pWebClient, SLOT(requestArtistPage(int)));
    connect(pQueueWidget->getHistoryListWidget(), SIGNAL(requestUserPage(QString)), pWebClient, SLOT(requestUserPage(QString)));

    connect(pPlayerWidget, SIGNAL(tooglePlayPauseStateSignal()), this, SLOT(tooglePlayPause()));
    connect(pPlayerWidget, SIGNAL(stopStateSignal()), this, SLOT(toogleStopMenu()));

    connect(pOnelinerTimer, SIGNAL(timeout()), this, SLOT(needLoadOneliner()));
    connect(pQueueTimer, SIGNAL(timeout()), this, SLOT(needLoadQueue()));
    connect(pUsersTimer, SIGNAL(timeout()), this, SLOT(needLoadUsers()));

    // Start the timer (now they will run for the whole program life)
    pOnelinerTimer->start(ONELINER_TIMER_FREQ);
    pQueueTimer->start(QUEUE_TIME_FREQ);
    pUsersTimer->start(USERS_TIME_FREQ);
    pPMTimer->setInterval(PM_TIME_FREQ);

    // Load a first time the info
    needLoadOneliner();
    needLoadQueue();
    needLoadUsers();

    qDebug() << "MainWindow created";
}

void MainWindow :: createMenus(void)
{
    /**
      File ->
       - Reload queue
       - Reload oneliner
       - =====
       - &Quit
    **/
    QMenu* fileMenu = new QMenu(tr("&File"),this);
    {
        Utils::addActionInMenu(this, fileMenu,QIcon(),tr("&Login"), "Ctrl+L", tr("Login to the server"),this, SLOT(needLogin()));
        fileMenu->addSeparator();
        Utils::addActionInMenu(this, fileMenu,QIcon(),tr("&Reload Queue"), "Ctrl+R", tr("Reload the queue from the server"),this,SLOT(needLoadQueue()));
        Utils::addActionInMenu(this, fileMenu,QIcon(),tr("&Reload Oneliner"), "Ctrl+T", tr("Reload the oneliner from the server"),this,SLOT(needLoadOneliner()));
        Utils::addActionInMenu(this, fileMenu,QIcon(ICONSDIR + QString("newspaper.png")),tr("&News"), "Ctrl+N", tr("Displays the news from the server"),this,SLOT(needLoadNews()));
        Utils::addActionInMenu(this, fileMenu,QIcon(ICONSDIR + QString("heart.png")),tr("Load &Favorite"), "Ctrl+F", tr("Displays the user's favs from the server"),this,SLOT(needLoadFavs()));
        pUserFavAction = Utils::addActionInMenu(this, fileMenu,QIcon(ICONSDIR + QString("heart.png")),tr("User's &Favorite"), "Ctrl+U", tr("Displays the user's favs from the server"),this,SLOT(needLoadUserFavs()));
        pUserFavAction->setVisible(false); // Only visible when the user is connected
        Utils::addActionInMenu(this, fileMenu,QIcon(ICONSDIR + QString("music.png")),tr("&Song page"), "Ctrl+O", tr("Displays the song page from the server"),this,SLOT(needLoadSong()));
        Utils::addActionInMenu(this, fileMenu,QIcon(ICONSDIR + QString("user_green.png")), tr("&Artist page"), "Ctrl+A", tr("Displays the artist page from the server"),this,SLOT(needLoadArtist()));
        Utils::addActionInMenu(this, fileMenu,QIcon(ICONSDIR + QString("group.png")), tr("&Group page"), "Ctrl+G", tr("Displays the group page from the server"),this,SLOT(needLoadGroup()));
        Utils::addActionInMenu(this, fileMenu,QIcon(ICONSDIR + QString("compilation.png")),tr("&Compilation page"), "Ctrl+C", tr("Displays the compilation page from the server"),this,SLOT(needLoadCompilation()));
        Utils::addActionInMenu(this, fileMenu,QIcon(ICONSDIR + QString("user_green.png")),tr("&User page"), "Ctrl+U", tr("Displays the user page from the server"),this,SLOT(needLoadUser()));
        pCheckPMAction = Utils::addActionInMenu(this, fileMenu,QIcon(),tr("Check if new PM"), "", tr("Display if you have new PM available"),this,SLOT(needLoadPMs()),false);
        Utils::addActionInMenu(this, fileMenu,QIcon(),tr("Reload &Users online"), "Ctrl+U", tr("Displays the users online"),this,SLOT(needLoadUsers()));
        fileMenu->addSeparator();
        Utils::addActionInMenu(this, fileMenu,QIcon(),tr("&Save History"), "Ctrl+H", tr("Save the history"),this,SLOT(needSaveHistory()));
        fileMenu->addSeparator();
        Utils::addActionInMenu(this, fileMenu,QIcon(),tr("&Quit"),"Ctrl+W",tr("Quit the application"),qApp,SLOT(quit()));

        this->menuBar()->addMenu(fileMenu);
    }

    /**
      View ->
       - Oneliner
       - Queue
       - Player
    **/
    QMenu* viewMenu = new QMenu(tr("&View"),this);
    {
        Utils::addActionInMenu(this, viewMenu,QIcon(), "&Oneliner", "Ctrl+O", tr("Displays the oneliner"), this, SLOT(needOnelinerWidget()));
        Utils::addActionInMenu(this, viewMenu,QIcon(), tr("&Queue"), "Ctrl+Q", tr("Displays the queue"), this, SLOT(needQueueWidget()));
        Utils::addActionInMenu(this, viewMenu,QIcon(), tr("Player"), "Ctrl+P", tr("Displays the player"), this, SLOT(needPlayerWidget()));
        viewMenu->addSeparator();

        this->menuBar()->addMenu(viewMenu);
    }

    /**
      Player ->
       - Play / Pause
       --------
       - Volume UP
       - Volume DOWN
       --------
       - Settings
    **/
    QMenu* playerMenu = new QMenu(tr("&Player"),this);
    {
        pPlayPauseAction = Utils::addActionInMenu(this, playerMenu,QIcon(), tr("&Play"), "Ctrl+P", tr("Play the stream"), this, SLOT(tooglePlayPause()));
        pStopAction = Utils::addActionInMenu(this, playerMenu,QIcon(), tr("&Stop"), "Ctrl+S", tr("Stops the stream"), this, SLOT(toogleStopMenu()));
        playerMenu->addSeparator();
        Utils::addActionInMenu(this, playerMenu,QIcon(), tr("Volume &UP"), "Ctrl++", tr("Increase the volume"), pPlayer, SLOT(increaseVolume()));
        Utils::addActionInMenu(this, playerMenu,QIcon(), tr("Volume &DOWN"), "Ctrl+-", tr("Decrease the volume"), pPlayer, SLOT(decreaseVolume()));
        Utils::addActionInMenu(this, playerMenu,QIcon(), tr("Mute / UnMute"), "Ctrl+M", tr("Mute / UnMute the volume"), pPlayer, SLOT(switchMuteVolume()));
        playerMenu->addSeparator();
        Utils::addActionInMenu(this, playerMenu,QIcon(), tr("Streams"), "Ctrl+S", tr("Displays the streams available and let you choose one"), this, SLOT(needLoadStream()));
        this->menuBar()->addMenu(playerMenu);
    }

    /**
      &Connection ->
    **/
    QMenu* connectMenu = new QMenu(tr("&Connection"),this);
    {
        Utils::addActionInMenu(this, connectMenu,QIcon(), tr("Oneliner frequency"), "", tr("Change the oneliner reloading frequency"), this, SLOT(needChangeOnelinerRefreshFreq()));
        Utils::addActionInMenu(this, connectMenu,QIcon(), tr("Users list frequency"), "", tr("Change the oneliner reloading frequency"), this, SLOT(needChangeUsersRefreshFreq()));
        Utils::addActionInMenu(this, connectMenu,QIcon(), tr("PM check frequency"), "", tr("Change the check of PM frequency"), this, SLOT(needChangePMCheckFreq()));
        connectMenu->addSeparator();
        pTooglePMAutoCheckAction = Utils::addActionInMenu(this, connectMenu,QIcon(), tr("PM Auto checking"), "", tr("Toogle if the application checks the PMs"), this, SLOT(needTooglePMAutoCheck()),true,true);
        connectMenu->addSeparator();
        pTooglePMAutoCheckAction = Utils::addActionInMenu(this, connectMenu,QIcon(), tr("Set Proxy"), "", tr("Set the use of a proxy"), this, SLOT(needSetProxy()));
        this->menuBar()->addMenu(connectMenu);
    }

    /**
      Settings ->
    **/
    QMenu* settingsMenu = new QMenu(tr("&Settings"),this);
    {
        this->menuBar()->addMenu(settingsMenu);
    }

    /**
      Help ->
    **/
    QMenu* helpMenu = new QMenu(tr("&Help"),this);
    {
        this->menuBar()->addMenu(helpMenu);
    }

    qDebug() << "Menus created";
}

MainWindow :: ~MainWindow()
{
    qDebug() << "MainWindow deleted";
}

void MainWindow :: closeEvent(QCloseEvent *pCE)
{
    qDebug() << "MainWindow :: closeEvent";

    this->closeOpenedWindows();
    pCE->accept();
}

void MainWindow :: needLogin()
{
    LoginPromptDialog lpd(this);

    qDebug() << "MainWindow needLogin";

    if ( lpd.exec() == QDialog::Accepted )
    {
        username = lpd.getLogin();
        pWebClient->login(lpd.getLogin(),lpd.getPassword());
    }
}

void MainWindow :: needLoadQueue()
{
    qDebug() << "MainWindow needLoadQueue";

    pWebClient->requestQueue();
}

void MainWindow :: needRefreshQueue()
{
    SongRequest sr;
    QList<SongRequest> pendingQueue;
    QList<SongRequest> historyQueue;

    qDebug() << "MainWindow needRefreshQueue";

    if ( Parser::readXMLQueueNow(pWebClient->getQueueData(),sr) != true )
    {
        QMessageBox::warning(this,tr("Parser error"),tr("Error while parsing the queue XML page (actual entry)"));
        pQueueTimer->start(QUEUE_TIME_FREQ);
        return;
    }

    this->pQueueWidget->setPlayingSong(sr);

    if ( Parser::readXMLQueuePending(pWebClient->getQueueData(),pendingQueue) != true )
    {
        QMessageBox::warning(this,tr("Parser error"),tr("Error while parsing the queue XML page (pending queue)"));
        pQueueTimer->start(QUEUE_TIME_FREQ);
        return;
    }

    this->pQueueWidget->setQueueData(pendingQueue);

    if ( Parser::readXMLQueueHistory(pWebClient->getQueueData(),historyQueue) != true )
    {
        QMessageBox::warning(this,tr("Parser error"),tr("Error while parsing the queue XML page (pending queue)"));
        pQueueTimer->start(QUEUE_TIME_FREQ);
        return;
    }

    this->pQueueWidget->setHistoryData(historyQueue);

    unsigned int msLeftBeforeNextSong = this->pQueueWidget->getTimeLeftBeforeNextSong()*1000;

    if ( msLeftBeforeNextSong != 0 )
    {
        pQueueTimer->start(msLeftBeforeNextSong);
    }
    else
    {
        pQueueTimer->start(QUEUE_TIME_FREQ);
    }

    qDebug() << "\tTime left before next song: " << msLeftBeforeNextSong;
}

void MainWindow :: needLoadOneliner()
{
    qDebug() << "MainWindow needLoadOneliner";

    pWebClient->requestOneliner();
}

void MainWindow :: needRefreshOneliner()
{
    qDebug() << "MainWindow needRefreshOneliner";

    pOnelinerWidget->setMessagesData(Parser::readXMLOneliner(pWebClient->getOnelinerData()));
}

void MainWindow :: needLoadStream()
{
    qDebug() << "MainWindow needLoadStream";

    pWebClient->requestStream();
}

void MainWindow :: needDisplayStream()
{
    QList<Stream> streams;

    qDebug() << "MainWindow needDisplayStream";

    if ( Parser::readXMLStream(pWebClient->getStreamData(), streams) )
    {
        StreamsPromptDialog spd(streams, pPlayer->getSource(), this);

        if ( spd.exec() == QDialog::Accepted )
        {
            pPlayer->setSource(spd.getSelectedSource());

            pPlayPauseAction->setText(tr("&Pause"));
            pPlayPauseAction->setToolTip(tr("Pauses the stream"));
            pStopAction->setEnabled(true);
            pPlayer->play();
        }
    }
    else
    {
        QMessageBox::warning(this,tr("Parser error"),tr("Error while parsing the streams XML page"));
    }
}

void MainWindow :: needLoadNews()
{
    qDebug() << "MainWindow needLoadNews";

    pWebClient->requestNews(NRR_News);
}

void MainWindow :: needDisplayNews()
{
    qDebug() << "MainWindow needDisplayNews";

    if ( pNPD == NULL )
    {
        QList<News>news;

        if ( Parser::readPageNews(pWebClient->getNewsData(),news) == false )
        {
            QMessageBox::warning(this,tr("Parser error"),tr("Error while parsing the news"));
            return;
        }

        pNPD = new NewsPromptDialog(news,needDisplayNewsAtStartup);

        connect(pNPD, SIGNAL(deleteNPDSignal()), this, SLOT(needDeleteNPD()));
    }

    pNPD->show();
}

void MainWindow :: needLoadFavs()
{
    QString user = "";
    bool isOk = true;

    qDebug() << "MainWindow needloadSong";

    user = QInputDialog::getText(this,tr("Insert the name of the user"),tr("User nick:"),QLineEdit::Normal,QString(),&isOk);
    if ( isOk )
    {
        pWebClient->requestFavoritePage(user,false);
    }
}

void MainWindow :: needLoadUserFavs(void)
{
    qDebug() << "MainWindow needLoadUserFavs (" << username << ")";

    pWebClient->requestFavoritePage(username,false);    // It's false, because I don't want to update again the user favorites list
    // And also because, if it was true, the user will never see his favorite viewer
}

void MainWindow :: needDisplayFavList()
{
    Favorites favs;
    FavsDialog* pFD = NULL;

    qDebug() << "MainWindow needDisplayFavList";

    if ( Parser::readPageFavs(pWebClient->getFavoritesData(),favs) == false )
    {
        QMessageBox::warning(this,tr("Parser error"),tr("Error while parsing the favorites"));
        return;
    }

    if ( favs.favs.count() == 0 )
    {
        QMessageBox::warning(this,tr("Favorite"),tr("You are not allowed to see this favorites pages"));
        return;
    }

    if ( isConnected )
    {
        if ( username == favs.owner )
        {
            pFD = new FavsDialog(favs,true,userFavorites,isConnected);
        }
        else
        {
            pFD = new FavsDialog(favs,false,userFavorites,isConnected);
        }
    }
    else
    {
        pFD = new FavsDialog(favs);
    }

    listPFD.push_back(pFD);
    connect(pFD, SIGNAL(deleteFDSignal(FavsDialog*)), this, SLOT(needDeleteFD(FavsDialog*)));

    connect(pFD, SIGNAL(needLoadPage(FavsDialog*, unsigned int)), this, SLOT(needGetFavPage(FavsDialog*, unsigned int)));
    connect(pFD, SIGNAL(needFav(int)), this, SLOT(needFavSong(int)));
    connect(pFD, SIGNAL(needUnfav(int)), this, SLOT(needUnFavSong(int)));
    connect(pFD, SIGNAL(needRequestSong(int)), this, SLOT(needRequestSong(int)));

    pFD->show();
}

void MainWindow :: needDisplayFavListPage()
{
    Favorites favs;
    FavsDialog* pFD = NULL;

    qDebug() << "MainWindow needDisplayFavListPage";

    if ( Parser::readPageFavs(pWebClient->getFavoritesData(),favs) == false )
    {
        QMessageBox::warning(this,tr("Parser error"),tr("Error while parsing the favorites"));
        return;
    }

    for ( QList<FavsDialog*>::const_iterator itPFD = pFDList.begin() ; itPFD != pFDList.end() && pFD == NULL ; ++itPFD )
    {
        if ( (*itPFD)->getOwner() == favs.owner )
        {
            pFD = *itPFD;
            if ( isConnected )
            {
                pFD->loadFavs(favs,userFavorites);
            }
            else
            {
                pFD->loadFavs(favs);
            }
        }
    }

    pFDList.removeOne(pFD);
}

void MainWindow :: needLoadSong()
{
    unsigned int id = 0;
    bool isOk = true;

    qDebug() << "MainWindow needloadSong";

    id = QInputDialog::getInt(this,tr("Insert the 'ID' of the song"),tr("Song ID:"),1,1,2147483647,1,&isOk);
    if ( isOk )
    {
        pWebClient->requestSongPage(id);
    }
}

void MainWindow :: needLoadArtist(void)
{
    unsigned int id = 0;
    bool isOk = true;

    qDebug() << "MainWindow needLoadArtist";

    id = QInputDialog::getInt(this,tr("Insert the 'ID' of the artist"),tr("Artist ID:"),1,1,2147483647,1,&isOk);
    if ( isOk )
    {
        pWebClient->requestArtistPage(id);
    }
}

void MainWindow :: needLoadGroup()
{
    unsigned int id = 0;
    bool isOk = true;

    qDebug() << "MainWindow needloadGroup";

    id = QInputDialog::getInt(this,tr("Insert the 'ID' of the group"),tr("Group ID:"),1,1,2147483647,1,&isOk);
    if ( isOk )
    {
        pWebClient->requestGroupPage(id);
    }
}

void MainWindow :: needLoadCompilation(void)
{
    unsigned int id = 0;
    bool isOk = true;

    qDebug() << "MainWindow needLoadCompilation";

    id = QInputDialog::getInt(this, tr("Insert the 'ID' of the compilation"),tr("Compilation ID:"),1,1,2147483647,1,&isOk);
    if ( isOk )
    {
        pWebClient->requestCompilationPage(id);
    }
}

void MainWindow :: needLoadUser(void)
{
    QString username;
    bool isOk = true;

    qDebug() << "MainWindow needLoadUser";

    username = QInputDialog::getText(this, tr("Insert the name of the user"),tr("User name:"),QLineEdit::Normal,"",&isOk);
    if ( isOk )
    {
        pWebClient->requestUserPage(username);
    }
}

void MainWindow :: needLoadUsers()
{
    qDebug() << "MainWindow needLoadUsers";

    pWebClient->requestNews(NRR_UserOnliner);
}

void MainWindow :: needLoadPMs(void)
{
    qDebug() << "MainWindow needLoadPMs";

    pmRequestedByUser = true;

    pWebClient->requestNews(NRR_Inbox);
}

void MainWindow :: needSetProxy()
{
    ProxyPromptDialog ppd(this);

    qDebug() << "MainWindow needSetProxy";

    if ( ppd.exec() == QDialog::Accepted )
    {
        pWebClient->defineProxy(ppd.getProxyType(),ppd.getHost(),ppd.getPort(),ppd.getLogin(),ppd.getPassword());
    }
}

void MainWindow :: needDisplaySong()
{
    Song s;
    SongInfoDialog* pTmpSID = NULL;

    qDebug() << "MainWindow needDisplaySong";

    if ( readSongPage(pWebClient->getSongData(),s) == false )
    {
        QMessageBox::warning(this,tr("Parser error"),tr("Fail to parse the song info page"));
        return;
    }

    pTmpSID = new SongInfoDialog(s);

    listPSID.push_back(pTmpSID);
    connect(pTmpSID, SIGNAL(deleteSIDSignal(SongInfoDialog*)), this, SLOT(needDeleteSID(SongInfoDialog*)));

    pTmpSID->show();
}

void MainWindow :: needDisplayArtist()
{
    Artist a;
    ArtistInfoDialog* pTmpAID = NULL;

    qDebug() << "MainWindow needDisplayArtist";

    if ( readArtistPage(pWebClient->getArtistData(),a) == false )
    {
        QMessageBox::warning(this,tr("Parser error"),tr("Fail to parse the artist info page"));
        return;
    }

    pTmpAID = new ArtistInfoDialog(a);

    listPAID.push_back(pTmpAID);
    connect(pTmpAID, SIGNAL(deleteAIDSignal(ArtistInfoDialog*)), this, SLOT(needDeleteAID(ArtistInfoDialog*)));

    pTmpAID->show();
}

void MainWindow :: needDisplayGroup()
{
    Group g;
    GroupInfoDialog* pTmpGID = NULL;

    qDebug() << "MainWindow needDisplayGroup";

    if ( readGroupPage(pWebClient->getGroupData(),g) == false )
    {
        QMessageBox::warning(this,tr("Parser error"),tr("Fail to parse the group info page"));
        return;
    }

    pTmpGID = new GroupInfoDialog(g);

    listPGID.push_back(pTmpGID);
    connect(pTmpGID, SIGNAL(deleteGIDSignal(GroupInfoDialog*)), this, SLOT(needDeleteGID(GroupInfoDialog*)));

    pTmpGID->show();
}

void MainWindow :: needDisplayCompilation()
{
    Compilation c;
    CompilationInfoDialog* pTmpCID = NULL;

    qDebug() << "MainWindow needDisplayCompilation";

    if ( readCompilationPage(pWebClient->getCompilationData(),c) == false )
    {
        QMessageBox::warning(this,tr("Parser error"),tr("Fail to parse the compilation info page"));
        return;
    }

    pTmpCID = new CompilationInfoDialog(c);

    listPCID.push_back(pTmpCID);
    connect(pTmpCID, SIGNAL(deleteCIDSignal(CompilationInfoDialog*)), this, SLOT(needDeleteCID(CompilationInfoDialog*)));

    pTmpCID->show();
}

void MainWindow :: needDisplayUser(QString username)
{
    User u;
    UserInfoDialog* pTmpUID = NULL;

    qDebug() << "MainWindow needDisplayUser";

    if ( readUserPage(pWebClient->getUserData(),u) == false )
    {
        QMessageBox::warning(this,tr("Parser error"),tr("Fail to parse the cuser info page"));
        return;
    }

    if ( u.isHidden )
    {
        QMessageBox::information(this,tr("User page access"),tr("The user has hidden the page"));
        return;
    }

    u.name = username;
    pTmpUID = new UserInfoDialog(u);

    listPUID.push_back(pTmpUID);
    connect(pTmpUID, SIGNAL(deleteUIDSignal(UserInfoDialog*)), this, SLOT(needDeleteUID(UserInfoDialog*)));

    pTmpUID->show();
}

void MainWindow :: needDisplayUsers()
{
    QList<User>users;

    qDebug() << "MainWindow needDisplayUsers";

    if ( Parser::readUsersOnline(pWebClient->getNewsData(),users) == false )
    {
        QMessageBox::warning(this,tr("Parser error"),tr("Error while parsing the users online page"));
        return;
    }

    pOnelinerWidget->setUserList(users);
}

void MainWindow :: needDisplayInbox(void)
{
    int nbNewMessages = 0;

    qDebug() << "MainWindow :: needDisplayInbox";

    if ( Parser::readNbNewPM(pWebClient->getNewsData(),nbNewMessages) == false )
    {
        QMessageBox::warning(this,tr("Parser error"),tr("Error while parsing the number of new PMs page"));
        return;
    }

    if ( nbNewMessages != 0 )
    {
        QMessageBox::StandardButton sb = QMessageBox::information(this,tr("NUP :: New PM to read"),tr("You have %1 new private messages to read\nDo you want to read these? (open your internet browser)").arg(nbNewMessages),QMessageBox::Yes,QMessageBox::No);
        if ( sb == QMessageBox::Yes )
        {
            QDesktopServices::openUrl(QString(DEFAULT_SERVER) + QString(INBOX_PATH) );
        }
        else if ( sb == QMessageBox::No )
        {
            pPMTimer->stop();
            // ToDo stop timer message
        }
    }
    else if ( pmRequestedByUser )
    {
        QMessageBox::information(this,tr("NUP :: No new PM to read"),tr("You do not have new PM"));
    }

    pmRequestedByUser = false;
}

void MainWindow :: needChangeOnelinerRefreshFreq(void)
{
    unsigned int frequency = 0;
    bool isOk = true;

    qDebug() << "MainWindow :: needChangeOnelinerRefreshFreq";

    frequency = QInputDialog::getInt(this, tr("Insert the frequency of realoading the oneliner"),tr("Frequency of reloading the oneliner (in seconds):"),pOnelinerTimer->interval()/1000,ONELINER_TIMER_FREQ/1000,2147483647,1,&isOk);
    if ( isOk )
    {
        pOnelinerTimer->setInterval(frequency*1000);
    }
}

void MainWindow :: needChangeUsersRefreshFreq(void)
{
    unsigned int frequency = 0;
    bool isOk = true;

    qDebug() << "MainWindow :: needChangeUsersRefreshFreq";

    frequency = QInputDialog::getInt(this, tr("Insert the frequency of realoading the users list"),tr("Frequency of reloading the users list (in minutes):"),pUsersTimer->interval()/(1000*3600),USERS_TIME_FREQ/(1000*3600)-5,2147483647,1,&isOk);
    if ( isOk )
    {
        pUsersTimer->setInterval(frequency*(1000*3600));
    }
}

void MainWindow :: needChangePMCheckFreq(void)
{
    unsigned int frequency = 0;
    bool isOk = true;

    qDebug() << "MainWindow :: needChangePMCheckFreq";

    frequency = QInputDialog::getInt(this, tr("Insert the frequency of checking the PMs"),tr("Frequency of checking the PM (in minutes):"),pPMTimer->interval()/(1000*3600),PM_TIME_FREQ/(1000*3600)-60,6*60,1,&isOk);
    if ( isOk )
    {
        pPMTimer->setInterval(frequency*(1000*3600));
    }
}

void MainWindow :: needTooglePMAutoCheck(void)
{
    bool isChecked = pTooglePMAutoCheckAction->isChecked();

    qDebug() << "MainWindow :: needTooglePMAutoCheck (" << isChecked << ")";

    if ( isChecked )
    {
        if ( isConnected )
        {
            pPMTimer->start();
        }
    }
    else
    {
        pPMTimer->stop();
    }
}

void MainWindow :: needGetFavPage(FavsDialog* pFD, const unsigned int pageNumber)
{
    qDebug() << "MainWindow needGetFavPage -> " << pageNumber;

    pFDList.push_back(pFD);

    pWebClient->requestFavoritePage(pFD->getOwner(),false,pageNumber);
}

void MainWindow :: needFavSong(const int id)
{
    qDebug() << "MainWindow needFavSong -> " << id;

    pWebClient->requestFavSong(id);
}

void MainWindow :: needUnFavSong(const int id)
{
    qDebug() << "MainWindow needUnFavSong -> " << id;

    pWebClient->requestUnFavSong(id);
}

void MainWindow :: needRequestSong(const int id)
{
    qDebug() << "MainWindow needRequestSong -> " << id;

    if ( pQueueWidget->getUserRequestCount(username) < SONG_REQUEST_LIMIT )
    {
        pWebClient->requestRequestSong(id);
        pWebClient->requestQueue();
    }
    else
    {
        QMessageBox::information(this,tr("NUP :: Request"),tr("You can't request more than %1 songs in a row").arg(SONG_REQUEST_LIMIT));
    }
}

void MainWindow :: connectionSucceed(void)
{
    qDebug() << "MainWindow :: connectionSucceed";

    isConnected = true;
    pWebClient->requestFavoritePage(username,true);
    pUserFavAction->setText(tr("%1's &Favorite").arg(username));
    pUserFavAction->setToolTip(tr("Displays the %1's favs from the server").arg(username));
    pUserFavAction->setVisible(true);
    pCheckPMAction->setEnabled(true);

    if ( pTooglePMAutoCheckAction->isChecked() )
    {
        pPMTimer->start();
    }

    pOnelinerWidget->setConnection(true);
    pQueueWidget->setConnection(true);

}

void MainWindow :: needDisplayConnectionFailure()
{
    qDebug() << "MainWindow needDisplayConnectionFailure";

    isConnected = false;
    username = "";
    userFavorites.clear();
    pUserFavAction->setVisible(false);
    pCheckPMAction->setEnabled(false);
    pPMTimer->stop();
    pOnelinerWidget->setConnection(false);
    pQueueWidget->setConnection(false);

    QMessageBox::warning(this,tr("Connection failed"),tr("The login/password are not correct"));
}

void MainWindow :: needDisplayWebError(QString errorMessage)
{
    qDebug() << "MainWindow needDisplayWebError";
    QMessageBox::warning(this,tr("WebClient failure"),errorMessage);
}

void MainWindow :: needTabToClose(int index)
{
    qDebug() << "MainWindow needTabToClose: " << index;

    pTabWidget->removeTab(index);    
}

void MainWindow :: needOnelinerWidget(void)
{
    qDebug() << "MainWindow needOnelinerWidget";

    if ( pTabWidget->indexOf(pOnelinerWidget) == -1 ) // If the tab doesn't exist
    {
        pTabWidget->addTab(pOnelinerWidget,"Oneliner");
    }

    // In all cases we are making it current
    pTabWidget->setCurrentWidget(pOnelinerWidget);
}

void MainWindow :: needQueueWidget(void)
{
    qDebug() << "MainWindow needQueueWidget";

    if ( pTabWidget->indexOf(pQueueWidget) == -1 ) // If the tab doesn't exist
    {
        pTabWidget->addTab(pQueueWidget,tr("Queue"));
    }

    // In all cases we are making it current
    pTabWidget->setCurrentWidget(pQueueWidget);
}

void MainWindow :: needPlayerWidget(void)
{
    qDebug() << "MainWindow needPlayerWidget";

    if ( pTabWidget->indexOf(pPlayerWidget) == -1 ) // If the tab doesn't exist
    {
        pTabWidget->addTab(pPlayerWidget,tr("Player"));
    }

    // In all cases we are making it current
    pTabWidget->setCurrentWidget(pPlayerWidget);
}

void MainWindow :: tooglePlayPause()
{
    qDebug() << "MainWindow tooglePlayPause (" << pPlayPauseAction->text() << ")";

    if ( pPlayPauseAction->text() == tr("&Play") )
    {
        pPlayPauseAction->setText(tr("&Pause"));
        pPlayPauseAction->setToolTip(tr("Pauses the stream"));

        pStopAction->setEnabled(true);

        pPlayer->play();
    }
    else if ( pPlayPauseAction->text() == tr("&Pause") )
    {
        pPlayPauseAction->setText(tr("&Play"));
        pPlayPauseAction->setToolTip(tr("Plays the stream"));

        pPlayer->pause();
    }

    pPlayerWidget->tooglePlayPauseState();
}

void MainWindow :: toogleStopMenu(void)
{
    qDebug() << "MainWindow toogleStopMenu (" << pStopAction->isEnabled() << ")";

    if ( pStopAction->isEnabled() == true )
    {
        pStopAction->setEnabled(false);
        pPlayPauseAction->setText(tr("&Play"));
        pPlayPauseAction->setToolTip(tr("Plays the stream"));

        pPlayerWidget->setStopState();
        pPlayer->stop();
    }
}

void MainWindow :: needUpdatePlayerInfo(void)
{
    qDebug() << "MainWindow :: needUpdatePlayerInfo";

    pPlayerWidget->updateInfo(pPlayer->getStreamInfo(),pPlayer->getSource().toString());
}

void MainWindow :: needDisplayPlayerError(const QString errorMessage)
{
    qDebug() << "MainWindow :: needDisplayPlayerError " << errorMessage;

    QMessageBox::warning(this,tr("Player error"),errorMessage);
    this->toogleStopMenu();
}

void MainWindow :: needUpdateUserFavorite(void)
{
    Favorites favs;

    qDebug() << "MainWindow :: needUpdateUserFavorite";

    Parser::readPageFavs(pWebClient->getFavoritesData(),favs);

    favs.favoritesToIDList(userFavorites);

    if ( favs.nbPages > 1 )
    {
        // In this case we need to request all other pages
        for ( unsigned int i = 2 ; i <= favs.nbPages ; i++ )
        {
            pWebClient->requestFavoritePage(favs.owner,true,i);
        }
    }
}

void MainWindow :: needUpdateUserPaginatedFavorite(void)
{
    Favorites favs;

    qDebug() << "MainWindow :: needUpdateUserPaginatedFavorite";

    Parser::readPageFavs(pWebClient->getFavoritesData(),favs);

    favs.favoritesAddToIDList(userFavorites);
}

void MainWindow :: needVote(int vote)
{
    qDebug() << "MainWindow :: needVote (" << vote << ")";

    pWebClient->requestVote(pQueueWidget->getSongRequestWidget()->getSongId(),vote);
}

void MainWindow :: needSaveHistory(void)
{
    QString fileName = QFileDialog::getSaveFileName(this, tr("Save oneliner history"), QDir::currentPath(), tr("HTML page (*.html)"));

    qDebug() << "MainWindow :: needSaveHistory" << fileName;

    if ( !fileName.isEmpty())
    {
        if ( !fileName.contains(".html"))
        {
            // if the file doesn't have the extension, we force it
            fileName.append(".html");
        }

        QFile file(fileName);

        if ( file.open(QIODevice::WriteOnly) )
        {
            file.write(pOnelinerWidget->getOnelinerData().toUtf8());
        }
        else
        {
            QMessageBox::critical(this,tr("Fail to save"),tr("Error while opening the file: '") + fileName + QString("'"));
        }

        file.close();
    }
}

void MainWindow :: needDeleteSID(SongInfoDialog* pSID)
{
    qDebug() << "MainWindow :: needDeleteSID";

    listPSID.removeOne(pSID);

    delete pSID;
}

void MainWindow :: needDeleteAID(ArtistInfoDialog* pAID)
{
    qDebug() << "MainWindow :: needDeleteAID";

    listPAID.removeOne(pAID);

    delete pAID;
}

void MainWindow :: needDeleteGID(GroupInfoDialog* pGID)
{
    qDebug() << "MainWindow :: needDeleteGID";

    listPGID.removeOne(pGID);

    delete pGID;
}

void MainWindow :: needDeleteCID(CompilationInfoDialog* pCID)
{
    qDebug() << "MainWindow :: needDeleteCID";

    listPCID.removeOne(pCID);

    delete pCID;
}

void MainWindow :: needDeleteUID(UserInfoDialog* pUID)
{
    qDebug() << "MainWindow :: needDeleteUID";

    listPUID.removeOne(pUID);

    delete pUID;
}

void MainWindow :: needDeleteFD(FavsDialog* pFD)
{
    qDebug() << "MainWindow :: needDeleteFD";

    listPFD.removeOne(pFD);

    delete pFD;
}

void MainWindow :: needDeleteNPD()
{
    qDebug() << "MainWindow :: needDeleteNewsPrompt";

    needDisplayNewsAtStartup = pNPD->hasNewsAtStartup();

    delete pNPD;
    pNPD = NULL;
}

void MainWindow :: closeOpenedWindows(void)
{
    qDebug() << "MainWindow :: closeOpenedWindows";

    for ( QList<SongInfoDialog*>::const_iterator itSID = listPSID.begin() ; itSID != listPSID.end() ; ++itSID)
    {
        (*itSID)->close();
    }

    for ( QList<ArtistInfoDialog*>::const_iterator itAID = listPAID.begin() ; itAID != listPAID.end() ; ++itAID)
    {
        (*itAID)->close();
    }

    for ( QList<GroupInfoDialog*>::const_iterator itGID = listPGID.begin() ; itGID != listPGID.end() ; ++itGID)
    {
        (*itGID)->close();
    }

    for ( QList<CompilationInfoDialog*>::const_iterator itCID = listPCID.begin() ; itCID != listPCID.end() ; ++itCID)
    {
        (*itCID)->close();
    }

    for ( QList<UserInfoDialog*>::const_iterator itUID = listPUID.begin() ; itUID != listPUID.end() ; ++itUID)
    {
        (*itUID)->close();
    }

    for ( QList<FavsDialog*>::const_iterator itFD = listPFD.begin() ; itFD != listPFD.end() ; ++itFD)
    {
        (*itFD)->close();
    }

    if ( pNPD )
    {
        pNPD->close();
        delete pNPD;
    }
}

void MainWindow :: loadSettings(void)
{
    QSettings settings(ORGANISATION, APP_NAME);

    // Main window settings
    settings.beginGroup("Window");
    resize(settings.value("size", QSize(640, 480)).toSize());
    move(settings.value("pos", QPoint(0, 0)).toPoint());
    settings.endGroup();

    // Oneliner widget settings
    settings.beginGroup("Oneliner Widget");
    {
        bool isOpened = true;
        int position = 0;
        bool isCurrent = true;

        // Getting the settings
        isOpened = settings.value("opened",isOpened).toBool();
        position = settings.value("position",position).toInt();
        isCurrent = settings.value("selected", isCurrent).toBool();

        // Apply the settings
        if ( isOpened == false) // By default we have it ... so just close it if needed
        {
            pTabWidget->removeTab(pTabWidget->indexOf(pOnelinerWidget));
        }
        else // We don't need to try to manage the tab when it's closed
        {
            if ( position != 1 ) // We have to move the tab
            {
                // First we remove
                pTabWidget->removeTab(pTabWidget->indexOf(pOnelinerWidget));
                // Then we add it at the good position
                pTabWidget->insertTab(position, pOnelinerWidget, "Oneliner");
            }

            if ( isCurrent )
            {
                pTabWidget->setCurrentWidget(pOnelinerWidget);
                pOnelinerWidget->setFocus();
            }
        }
    }
    settings.endGroup();

    // Queue widget settings
    settings.beginGroup("Queue Widget");
    {
        bool isOpened = true;
        int position = 1;
        bool isCurrent = false;

        // Getting the settings
        isOpened = settings.value("opened",isOpened).toBool();
        position = settings.value("position",position).toInt();
        isCurrent = settings.value("selected", isCurrent).toBool();

        // Apply the settings
        if ( isOpened == false) // By default we have it ... so just close it if needed
        {
            pTabWidget->removeTab(pTabWidget->indexOf(pQueueWidget));
        }
        else // We don't need to try to manage the tab when it's closed
        {
            if ( position != 1 ) // We have to move the tab
            {
                // First we remove
                pTabWidget->removeTab(pTabWidget->indexOf(pQueueWidget));
                // Then we add it at the good position
                pTabWidget->insertTab(position, pQueueWidget, tr("Queue"));
            }

            if ( isCurrent )
            {
                pTabWidget->setCurrentWidget(pQueueWidget);
                pQueueWidget->setFocus();
            }
        }
    }
    settings.endGroup();

    // Player widget settings
    settings.beginGroup("Player Widget");
    {
        bool isOpened = true;
        int position = 2;
        bool isCurrent = false;

        // Getting the settings
        isOpened = settings.value("opened",isOpened).toBool();
        position = settings.value("position",position).toInt();
        isCurrent = settings.value("selected", isCurrent).toBool();

        // Apply the settings
        if ( isOpened == false) // By default we have it ... so just close it if needed
        {
            pTabWidget->removeTab(pTabWidget->indexOf(pPlayerWidget));
        }
        else // We don't need to try to manage the tab when it's closed
        {
            if ( position != 2 ) // We have to move the tab
            {
                // First we remove
                pTabWidget->removeTab(pTabWidget->indexOf(pPlayerWidget));
                // Then we add it at the good position
                pTabWidget->insertTab(position, pPlayerWidget, tr("Player"));
            }

            if ( isCurrent )
            {
                pTabWidget->setCurrentWidget(pPlayerWidget);
                pPlayerWidget->setFocus();
            }
        }

        pPlayer->setSource(QUrl(settings.value("stream-source",QUrl("http://demovibes.de:8000/necta128.ogg")).toString()));
    }
    settings.endGroup();

    settings.beginGroup("Connection");
    {
        pOnelinerTimer->setInterval(settings.value("oneliner-frequency",ONELINER_TIMER_FREQ).toInt());
        pUsersTimer->setInterval(settings.value("userslist-frequency",USERS_TIME_FREQ).toInt());
        pPMTimer->setInterval(settings.value("pmcheck-frequency",PM_TIME_FREQ).toInt());
        pTooglePMAutoCheckAction->setChecked(settings.value("pmautocheck",true).toBool());

        settings.beginGroup("Proxy");
        {
            QNetworkProxy::ProxyType type = static_cast<QNetworkProxy::ProxyType>(settings.value("type",QNetworkProxy::Socks5Proxy).toInt());
            QString host = settings.value("hostname","").toString();
            short unsigned int port = settings.value("port",0).toInt();

            if ( !host.isEmpty() && port!=0 )
            {
                pWebClient->defineProxy(type,host,port);
            }
            settings.endGroup();
        }
    }
    settings.endGroup();

    settings.beginGroup("Application");
    {
        needDisplayNewsAtStartup = settings.value("newsAtStartup",true).toBool();
    }
    settings.endGroup();

    // Starting the music
    tooglePlayPause();

    if ( needDisplayNewsAtStartup )
    {
        needLoadNews();
    }

    qDebug() << "MainWindow :: loadSettings -> settings loaded";
}

void MainWindow :: saveSettings(void)
{
    QSettings settings(ORGANISATION, APP_NAME);

    // Main window settings
    settings.beginGroup("Window");
    settings.setValue("size", size());
    settings.setValue("pos", pos());
    settings.endGroup();

    // Oneliner widget settings
    settings.beginGroup("Oneliner Widget");
    {
        // If it is closed
        if ( pTabWidget->indexOf(pOnelinerWidget) == -1 )
        {
            settings.setValue("opened",false);
        }
        else
        {
            settings.setValue("opened",true);
        }

        // Save the position of the tab ...
        settings.setValue("position",pTabWidget->indexOf(pOnelinerWidget)); // Will return -1 if not found

        // If it is selected actually
        if ( pTabWidget->currentWidget() == pOnelinerWidget )
        {
            settings.setValue("selected",true);
        }
        else
        {
            settings.setValue("selected",false);
        }
    }
    settings.endGroup();

    // Queue widget settings
    settings.beginGroup("Queue Widget");
    {
        // If it is closed
        if ( pTabWidget->indexOf(pQueueWidget) == -1 )
        {
            settings.setValue("opened",false);
        }
        else
        {
            settings.setValue("opened",true);
        }

        // Save the position of the tab ...
        settings.setValue("position",pTabWidget->indexOf(pQueueWidget)); // Will return -1 if not found

        // If it is selected actually
        if ( pTabWidget->currentWidget() == pQueueWidget )
        {
            settings.setValue("selected",true);
        }
        else
        {
            settings.setValue("selected",false);
        }
    }
    settings.endGroup();

    // Player widget settings
    settings.beginGroup("Player Widget");
    {
        // If it is closed
        if ( pTabWidget->indexOf(pPlayerWidget) == -1 )
        {
            settings.setValue("opened",false);
        }
        else
        {
            settings.setValue("opened",true);
        }

        // Save the position of the tab ...
        settings.setValue("position",pTabWidget->indexOf(pPlayerWidget)); // Will return -1 if not found

        // If it is selected actually
        if ( pTabWidget->currentWidget() == pPlayerWidget )
        {
            settings.setValue("selected",true);
        }
        else
        {
            settings.setValue("selected",false);
        }

        settings.setValue("stream-source",pPlayer->getSource());
    }
    settings.endGroup();

    settings.beginGroup("Connection");
    {
        settings.setValue("oneliner-frequency",pOnelinerTimer->interval());
        settings.setValue("userslist-frequency",pUsersTimer->interval());
        settings.setValue("pmcheck-frequency",pPMTimer->interval());
        settings.setValue("pmautocheck",pTooglePMAutoCheckAction->isChecked());

        settings.beginGroup("Proxy");
        settings.setValue("type",static_cast<int>(pWebClient->getProxyType()));
        settings.setValue("hostname",pWebClient->getProxyHost());
        settings.setValue("port",pWebClient->getProxyPort());
        settings.endGroup();
    }
    settings.endGroup();

    settings.beginGroup("Application");
    {
        settings.setValue("newsAtStartup",needDisplayNewsAtStartup);
    }
    settings.endGroup();

    qDebug() << "MainWindow :: saveSettings -> settings saved";
}
